package com.cg.service.impl;

import com.alibaba.fastjson.JSON;
import com.cg.dao.PatientMapper;
import com.cg.dao.PatientUserMapper;
import com.cg.dao.SmsLogMapper;
import com.cg.dto.*;
import com.cg.entity.Patient;
import com.cg.entity.PatientUser;
import com.cg.entity.SmsLog;
import com.cg.service.CodeService;
import com.cg.service.PatientUserService;
import com.cg.service.PatientUserTokenService;
import com.cg.service.SmsService;
import com.cg.utils.MD5Utils;
import com.cg.utils.TokenUtils;
import com.cg.vo.LoginPatientUserVo;
import com.google.gson.Gson;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Map;

/**
 * (PatientUser)表服务实现类
 *
 * @author chengong
 * @since 2023-12-31 13:47:45
 */
@Service("patientUserService")
public class PatientUserServiceImpl implements PatientUserService {
    @Resource
    private PatientUserMapper patientUserMapper;

    @Resource
    private PatientMapper patientMapper;

    @Resource
    private CodeService codeService;

    @Resource
    private SmsService smsService;

    @Resource
    private SmsLogMapper smsLogMapper;

    @Resource
    private PatientUserTokenService patientUserTokenService;

    /**
     * 获取注册需要的手机验证码
     */
    @Override
    public Result getCode(String phone) {
        //先验证1分钟之内有没有发送给（1分钟之内如果已经发送给了，不能重复发送）
        String value = codeService.getCode(phone);
        if (value != null) {
            return ResultUtils.returnResult(ResultEnum.FAIL_PHONE_EXIST);
        }
        //验证手机号是否已经注册过了
        Integer count = patientUserMapper.queryCountByPhone(phone);
        if (count > 0) {
            return ResultUtils.returnResult(ResultEnum.FAIL_PHONE_ACCOUNT);
        }
        //生成验证码
        String code = codeService.createCode(phone);
        //发送短信方法,并保存日志
        Result result = sendCode(phone, code);
        return result;
    }

    /**
     * 注册用户
     */
    @Override
    public Result createPatientUser(RegisterPatientUserDto registerPatientUserDto) {
        //根据前端传递的手机号从redis中获取value
/*        //先获取1分钟的呢个
        String value = codeService.getCode(registerPatientUserDto.getPhone());
        //如果一分钟的呢个不存在则获取3分钟的呢个*/
        String value = codeService.getCodeThree(registerPatientUserDto.getPhone());
        if(value == null || value.equals("")){
            return ResultUtils.returnResult(ResultEnum.PHONE_CODE_NULL);
        }

        PatientUser login = patientUserMapper.login(registerPatientUserDto.getPhone());
        if(login != null){
            return ResultUtils.returnResult(ResultEnum.FAIL_PHONE_ACCOUNT);
        }

        //比较判断验证码是否相等
        Boolean result = codeService.checkCode(registerPatientUserDto.getPhone(), registerPatientUserDto.getCode());
        if(!result){
            return ResultUtils.returnResult(ResultEnum.PHONE_CODE_ERROR);
        }
        //相同，下一步
        //进行密码加密处理
        //获取前端传递的密码
        String password = registerPatientUserDto.getPassword();
        //生成随机盐
        String salt = MD5Utils.getSalt();
        //对密码进行哈希处理,生成加密后的密码
        String newPassword = MD5Utils.saltMD5(salt, password);

        //组合对象
        PatientUser patientUser = new PatientUser();
        patientUser.setPhone(registerPatientUserDto.getPhone());
        patientUser.setPassword(newPassword);
        patientUser.setSalt(salt);

        System.out.println(patientUser);
        //添加
        Integer count = patientUserMapper.createPatientUser(patientUser);
        if(count <=0){
            return ResultUtils.returnResult(ResultEnum.PATIENT_USER_CREATE_ERROR);
        }

        return ResultUtils.returnSuccess();
    }

    /**
     * 获取登录的手机验证码
     */
    @Override
    public Result getLoginCode(String phone) {
        //验证手机号是否已经注册过了，如果已经注册过了，发送验证码，如果没有注册过，提示用户注册
        Integer count = patientUserMapper.queryCountByPhone(phone);
        if(count <= 0){
            //没有注册，不能登录，先注册
            return ResultUtils.returnResult(ResultEnum.FAIL_PHONE_NO_ACCOUNT);
        }
        //已经注册过了
        //验证1分钟之内是否已经发送过验证码了
        String value = codeService.getCode(phone+"login");
        if (value != null){
            return ResultUtils.returnResult(ResultEnum.FAIL_PHONE_EXIST);
        }
        //生成验证码
        String code = codeService.createCode(phone+"login");
        //发送短信方法,并保存日志
        Result result = sendCode(phone, code);
        return result;
    }

    /**
     * 患者登录
     */
    @Override
    public Result<LoginPatientUserVo> loginPatientUser(LoginPatientUserDto loginPatientUserDto) {
        //获取前端传递的手机号
        String phone = loginPatientUserDto.getPhone();
        //用户输入的code验证码
        String code = loginPatientUserDto.getCode();
        //用户输入的密码
        String password = loginPatientUserDto.getPassword();
        //验证手机号是否已经注册了，如果已经注册了，获取验证码或者密码登录，没有注册，提示用户

        Integer count = patientUserMapper.queryCountByPhone(phone);
        if(count <= 0){
            //没有注册过
            return ResultUtils.returnResult(ResultEnum.FAIL_PHONE_NO_ACCOUNT);
        }

        PatientUser patientUser = patientUserMapper.login(phone);

        if(patientUser == null){
            return ResultUtils.returnResult(ResultEnum.FAIL_PHONE_NO_ACCOUNT);
        }
        //通过手机号查询在redis中保存的默认患者的信息

        //手机验证码登录
        if(code!= null && !code.equals("")){
            //手机验证码登录
            //比较判断验证码是否相等
            Boolean result = codeService.checkCode(phone+"login", code);
            if(!result){
                return ResultUtils.returnResult(ResultEnum.PHONE_CODE_ERROR);
            }
            //验证码正确的情况
            //发送验证码并保存到消息表
            sendCode(phone, code);
            //保存到redis中
            /*
            patientUserTokenService.setPatientUserToken(patientUserVo);
            return ResultUtils.returnDataSuccess(patientUserVo);
            */
            //查询默认就诊人
            LoginPatientUserVo loginPatientUserVo = getLoginPatientUserVo(patientUser.getId(), loginPatientUserDto);
            return ResultUtils.returnDataSuccess(loginPatientUserVo);
        }

        //手机号和密码登录
        if(password != null && !password.equals("")){
            //验证密码
            String passwordSql = patientUser.getPassword();//数据库里面的密码，是已经加密的
            //获取盐
            String salt = patientUser.getSalt();
            //前端传递的密码加密
            password = MD5Utils.saltMD5(salt,password);
            //比较两密码是否一致
            if(!password.equals(passwordSql)){
                //密码不一致
                return ResultUtils.returnResult(ResultEnum.LOGIN_PASSWORD_ERROR);
            }
            //密码一致
            //查询默认就诊人
            LoginPatientUserVo loginPatientUserVo = getLoginPatientUserVo(patientUser.getId(), loginPatientUserDto);
            return ResultUtils.returnDataSuccess(loginPatientUserVo);
        }
        return null;
    }

    /**
     * 查询默认就诊人,并保存到redis中
     */
    public LoginPatientUserVo getLoginPatientUserVo(Integer patientUserId,LoginPatientUserDto loginPatientUserDto){
        //查询默认就诊人
        Patient patient = patientMapper.isDefaultByPatientUserId(patientUserId);
        if (patient == null){
            loginPatientUserDto.setPatientUserId(0);
        }
        loginPatientUserDto.setPatientUserId(patientUserId);
        String tokenKey = TokenUtils.createToken(loginPatientUserDto);
        String value = "";
        LoginPatientUserVo loginPatientUserVo = new LoginPatientUserVo();

        if(patient == null){
            loginPatientUserVo.setToken(tokenKey);
            value = JSON.toJSONString(loginPatientUserVo);
            patientUserTokenService.setKey(tokenKey,value);
        }
        //保存到redis中，安全起见，密码赋空值
        //patientUserTokenService.setPatientUserToken(patientUserVo);
        loginPatientUserVo.setPatient(patient);
        loginPatientUserVo.setToken(tokenKey);
        value = JSON.toJSONString(loginPatientUserVo);
        patientUserTokenService.setKey(tokenKey,value);
        return loginPatientUserVo;
    }



    /**
     * 修改密码
     */
    @Override
    public Result updatePassword(UpdatePasswordDto updatePasswordDto) {
        //输入的手机号
        String phone = updatePasswordDto.getPhone();
        //输入的老密码
        String password = updatePasswordDto.getPassword();
        //输入的新密码
        String passwordNew = updatePasswordDto.getPasswordNew();

        //根据手机号查询表中对应患者信息
        PatientUser patientUser = patientUserMapper.queryPatientUserByPhone(phone);
        if(patientUser == null){
            //未注册
            return ResultUtils.returnResult(ResultEnum.FAIL_PHONE_NO_ACCOUNT);
        }
        if(password == null || password.equals("")){
            //旧密码为空
            return ResultUtils.returnResult(ResultEnum.UPDATE_PASSWORD_NULL);
        }
        if(passwordNew == null || passwordNew.equals("")){
            //新密码为空
            return ResultUtils.returnResult(ResultEnum.UPDATE_PASSWORD_NEW_NULL);
        }

        //已经注册
        //判断输入的旧密码是否和数据库的一致
        //获取之前的盐
        String salt = patientUser.getSalt();
        password = MD5Utils.saltMD5(salt,password);
        if(!password.equals(patientUser.getPassword())){
            //旧密码错误
            return ResultUtils.returnResult(ResultEnum.LOGIN_PASSWORD_ERROR);
        }
        //新密码加密
        passwordNew = MD5Utils.saltMD5(salt,passwordNew);

        //新密码不能和旧密码一致
        System.out.println(passwordNew);
        if(passwordNew.equals(patientUser.getPassword())){
            return ResultUtils.returnResult(ResultEnum.UPDATE_PASSWORD_ERROR);
        }

        updatePasswordDto.setPassword(password);
        updatePasswordDto.setPasswordNew(passwordNew);
        updatePasswordDto.setPhone(phone);

        //修改密码
        Integer count = patientUserMapper.updatePassword(updatePasswordDto);
        if(count <= 0){
            return ResultUtils.returnResult(ResultEnum.COMMON_EXCEPTION);
        }
        return ResultUtils.returnSuccess();
    }

    /**
     * 发送短信方法,并保存日志
     */
    private Result sendCode(String phone,String code){
        //发送短信
        String sendCode = smsService.sendCode(phone, code);
        //转换成map格式的
        Gson gson = new Gson();
        Map<String,String> map = gson.fromJson(sendCode,Map.class);
        //判断消息是否发送成功
        //新增消息记录表
        SmsLog smsLog = new SmsLog();
        smsLog.setCodetype(0);
        smsLog.setPhone(phone);
        smsLog.setMessage(code);
        smsLog.setFailinfo(sendCode);
        if (map.get("code").equals("OK")) {
            //消息发送成功
            //发送成功在消息发送表记录成功的记录
            smsLog.setStatus(1);
            smsLogMapper.addSmsLog(smsLog);
            return ResultUtils.returnSuccess();
        }
        //消息发送失败
        //在消息表中记录消息发送失败的记录
        smsLog.setStatus(2);
        smsLogMapper.addSmsLog(smsLog);
        return ResultUtils.returnResult(ResultEnum.FAIL_SMS_SEND);
    }

}
